﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Updater.Core;
using RRQMProxy.Client;
using TouchSocket.Core;
using System.Net;

namespace Updater
{
    internal static class Program
    {
        //更新成功标识
        static bool isSuccess=true;
        
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            string doc = AppDomain.CurrentDomain.BaseDirectory;
            Console.WriteLine(doc);
            string title = ConfigurationManager.AppSettings["Title"];
            string ip = ConfigurationManager.AppSettings["ServerIp"];
            int port = int.Parse(ConfigurationManager.AppSettings["ServerPort"]);
            string Realm= ConfigurationManager.AppSettings["Realm"];
            if (Realm!="")
            {
                ip = Dns.GetHostAddresses(Realm)[0].ToString();
            }


            Console.Title = title + $"[{ip}:{port}]";
            
            UPTcpClient uPTcpClient = new UPTcpClient(ip, port);
         
            if (!uPTcpClient.Connetc())
            {
                uPTcpClient.Message("连接不到服务器，请检查通讯,3秒后退出");
                Thread.Sleep(3000);
                CallBack();
                return;
            }
            if (!File.Exists(doc+"UpdateConfiguration.xml"))
            {

                //不存在则新建一个文件
                UpdateConfiguration updateConfiguration = new UpdateConfiguration();
                updateConfiguration.Save(doc + "UpdateConfiguration.xml");
            }
            //1.获取本地的config
            UpdateConfiguration config = FastJson.Load<UpdateConfiguration>(doc + "UpdateConfiguration.xml");
            //2.获取服务器的config
            UpRpcServer upRpcServer = new UpRpcServer(uPTcpClient.Client);
            UpdateConfiguration ServerConfig = upRpcServer.GetLatestConfig();
            uPTcpClient.Message($"远端版本号：[{ServerConfig.ClientVersion}]本地版本号：[{config.ClientVersion}]");
            //检测是否需要更新
            if (config.ClientVersion== ServerConfig.ClientVersion)
            {
                uPTcpClient.Message($"检测到无需更新,三秒后退出");
                Thread.Sleep(3000);
                CallBack();
                return;
                //没有新版本
            }
            //运行到这里说明需要更新



            //3.计算要更新的文件
            //3.1确保temp文件夹存在
            FileHelper.SureDirExistence(doc + "temp\\");
            UpdateConfigInfo info = FileHelper.GetUpdateConfigInfo(config, ServerConfig.FileList);
            uPTcpClient.Message($"需要下载的数量：[{info.Add.Count+info.Change.Count},需要删除的数量{info.Delete.Count}]");
            int i = 1;
            int count = info.Add.Count + info.Change.Count;

          //  uPTcpClient.DownloadFile("FileFolder\\NLog.config", "temp\\NLog.config", i, count);
          //  Console.ReadKey();


            foreach (FileUnit item in info.Add)
            {
                string path = "FileFolder\\" +item.FileRelativePath;
                string sanvepath= doc + "temp\\" +item.FileRelativePath;
                //目标的文件夹名
                string despath = System.IO.Path.GetDirectoryName(sanvepath);
                //确保目标的文件夹存在
                FileHelper.SureDirExistence(despath);
                Task<string> x = uPTcpClient.DownloadFile(path, sanvepath, i++, count);
                x.Wait();
                if (x.Result!="Success")
                {
                    /*/出现错误重新下载10次
                    for (int k = 0; k < 10; k++)
                    {
                        uPTcpClient.Message($"尝试重新下载{k}");
                        string w = uPTcpClient.DownloadFile(path, sanvepath, i, count);
                        Thread.Sleep(5000);
                        if (x == "Success")
                        {
                            break;
                        }
                        if (k==9)
                        {
                            uPTcpClient.Message("下载过程出现失败停止下载，3秒后退出");
                            Thread.Sleep(3000);
                            Console.ReadKey();
                            return;
                        }


                    }*/

                    uPTcpClient.Message("下载过程出现失败停止下载，3秒后退出");
                    Thread.Sleep(3000);
                    Console.ReadKey();
                    return;

                }
               
                
            }
            foreach (FileUnit item in info.Change)
            {
                string path = "FileFolder\\" +item.FileRelativePath;
                string sanvepath = doc + "temp\\" + item.FileRelativePath;
                //目标的文件夹名
                string despath = System.IO.Path.GetDirectoryName(sanvepath);
                //确保目标的文件夹存在
                FileHelper.SureDirExistence(despath);
                Task<string> x = uPTcpClient.DownloadFile(path, sanvepath,i++,count);
                x.Wait();
                if (x.Result != "Success")
                {
                    uPTcpClient.Message("下载过程出现失败停止下载，3秒后退出");
                    Thread.Sleep(3000);
                    return;
                }
                Thread.Sleep(1000);
                
            }
            
            //运行到这里代表下载完成，通过issuccess判断是否成功
            if (!isSuccess)
            {
                uPTcpClient.Message("更新失败！！！按任意键退出");
                Console.ReadKey();
                return;
            }
            DirectoryInfo dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
            string calldir = dir.Parent.FullName;
            try
            {
                uPTcpClient.Message("下载文件完成，开始最后整理操作");
                //运行到这里代表文件验证已经成功开始复制文件
                FileHelper.CopyDirectory(AppDomain.CurrentDomain.BaseDirectory + "temp", calldir);
            }
            catch (Exception e)
            {
                uPTcpClient.Message("复制文件过程发生了失败,请重新更新,或者手动复制TEMP文件夹，按任意键退出");
                uPTcpClient.Message(e.Message);
                Console.ReadKey();
                return;
            }
            //运行到这里说明已经可以删除temp文件夹了
            DirectoryInfo di = new DirectoryInfo(doc+"temp");
            if (di.Exists)
            {
                if (di.GetFiles().Length+di.GetDirectories().Length==0)
                {
                    //目录为空

                    di.Delete();
                }
                else
                {
                    di.Delete(true);
                }
                
            }
            else
            {
                uPTcpClient.Message("删除temp文件的时候 temp不存在,按任意键退出");
                Console.ReadKey();
                return;
            }
            try
            {
                //运行到这里说明已经覆盖完成现在开始删除需要删除的文件
                foreach (FileUnit item in info.Delete)
                {
                    File.Delete(calldir + "\\" + item.FileRelativePath);
                }
            }
            catch (Exception e)
            {

                uPTcpClient.Message(e.Message);
            }
            ServerConfig.Save(doc+"UpdateConfiguration.xml");
            uPTcpClient.Message("更新完成，5秒后退出，回调");
            Thread.Sleep(1000);
            uPTcpClient.Message("更新完成，4秒后退出，回调");
            Thread.Sleep(1000);
            uPTcpClient.Message("更新完成，3秒后退出，回调");
            Thread.Sleep(1000);
            uPTcpClient.Message("更新完成，2秒后退出，回调");
            Thread.Sleep(1000);
            uPTcpClient.Message("更新完成，1秒后退出，回调");
            Thread.Sleep(1000);
             CallBack();

           
            
        }

     

        /// <summary>
        /// 启用升级完成后的程序
        /// </summary>
        public static void CallBack()
        {
            string filename = ConfigurationManager.AppSettings["CallbackExeName"];
            DirectoryInfo dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
            string callBackPath= dir.Parent.FullName + "\\"+filename;
            Console.WriteLine(callBackPath);
            if (File.Exists(callBackPath))
            {
                System.Diagnostics.Process myProcess = System.Diagnostics.Process.Start(callBackPath);
            }
        }
    }
}
